New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Image] Add onLoadStart, onLoadProgress, onLoadError events to Image component #1318
Conversation
|
||
@interface RCTDownloadTaskWrapper : NSObject <NSURLSessionDownloadDelegate> | ||
|
||
@property(nonatomic,assign) id<NSURLSessionDownloadDelegate> delegate; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: One space after @property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delegates should have "weak" retain semantics.
Sorry for all the nitpicks. |
Thank you so much! Could you help me about tests and other possible performances issues? As you mentioned before |
{ | ||
NSString *cacheKey = RCTCacheKeyForURL(url); | ||
__weak RCTImageDownloader *weakSelf = self; | ||
return [self _downloadDataForURL:url block:^(BOOL cached, NSData *data, NSError *error) { | ||
return [self _downloadDataForURL:url progressBlock:(RCTDataProgressBlock)progressBlock block:^(BOOL cached, NSData *data, NSError *error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to cast the blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
Thanks for all of the work here people, looking forward to seeing this in 😄 |
Merged from upstream (new lines about resizing etc), I've got unnecessary commits, it looks unclean now. I use this branch in production, though, don't know what to do next exactly. Tests? Rebase? |
@a2 - any chance you have a bit of time to ❤️ this PR? |
As for the API you may want to study https://html.spec.whatwg.org/multipage/embedded-content.html#mediaevents to see if any of the concepts are worth sharing (cc @vjeux) |
@ide thanks, good point. I consider to adding the |
@vjeux - can you shed any light on how you'd like to do naming for these types of events, as per @UnknownException comment above? |
This would be super useful, especially if the loaded data got passed back on success in base64 encoded string or some workable format. |
Waiting on event naming convention comments. |
I like the naming from the spec:
No. We never want to read image data in js. This means sending a huge chunk of memory (several megabytes) to js. There are some places where js is not a good language and doing image processing is one of them. You should be manipulating the image using C or the GPU. Not js with a base64 encoded file. |
_downloadToken = [_imageDownloader downloadImageForURL:imageURL size:self.bounds.size scale:RCTScreenScale() resizeMode:self.contentMode backgroundColor:self.backgroundColor block:^(UIImage *image, NSError *error) { | ||
_downloadToken = [_imageDownloader downloadImageForURL:imageURL size:self.bounds.size scale:RCTScreenScale() | ||
resizeMode:self.contentMode backgroundColor:self.backgroundColor | ||
progressBlock:progressHandler block:^(UIImage *image, NSError *error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you not update progress if there is no onProgress callback setup in js? This is wasteful to send events that are not going to be handled. (I'm not familiar with iOS so i'm not sure if you already do that, sorry if it's the case)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. There is a slightly tricky edge case to handle: on the Image's first render pass we don't provide an onProgress handler, and then provide one on the second pass. So the view/viewmanager needs to enable/disable the progress events when the onProgress handler prop is set/removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for comments, I renamed events and tried to not fire the progress event if it's not defined.
Tested this behavior with something like this:
class TestNetworkImage extends Component {
componentDidMount() {
setTimeout(() => {
this.setState({
onProgress: this.onProgress.bind(this)
})
}, 1000);
}
render() {
return <Image ref="image"
source={{uri: this.props.source}}
onLoadProgress={this.state.onProgress}>
{this.props.loader}
{this.props.children}
</Image>
}
}
NSLog
shows that at first second ImageView doesn't send an event to js in that case, then it does.
The app which uses these changes has passed Apple review and available on AppStore. It's not a good thing to maintain the fork, so I need to figure out how to split it into the stand-alone plugin. |
@UnknownException - I would love to see this merged upstream, @a2 - do you have any time to review again? Also, @UnknownException - can you please rebase? |
@facebook-github-bot import |
Thanks for importing. If you are an FB employee go to https://our.intern.facebook.com/intern/opensource/github/pull_request/470962509718878/int_phab to review. |
❤️ @a2 |
1ea70c1
to
3aed7c2
Compare
3aed7c2
to
7c856f5
Compare
Synced with the master and rebased. I had to adopt the new caching mechanism ( |
@UnknownException - if you can add an example to UIExplorer and submit in a separate PR that would be lovely! |
There are some code snippets that use `var` for declaring `styles` whereas some other snippets use `const`. Modified the page to all use `const` for consistency.
…cebook#439)" (facebook#1318) This change reverts microsoft#459 - but still tries to address the original issues: - microsoft#422 - microsoft#322 This also addresses an issue when programmatically resizing windows where the RCTRootContentView may end up at the wrong size because an in-flight layout gets resolved after the resize on the main thread. We now keep sync dispatch on the shadow queue for live resizing windows (to prevent tearing) but also dispatch async (as done on iOS) so the latest new size is sure to win. The block has a check to bail if the size doesn't change, so this isn't a perf drain running the block twice. Co-authored-by: Scott Kyle <skyle@fb.com>
This PR adds 4 native events to NetworkImage.
Using these events I could wrap
Image
component into something like:Useful on slow connections and server errors.
There are dozen lines of Objective C, which I don't have experience with. There are neither specific tests nor documentation yet. And I do realize that you're already working right now on better
<Image/>
(pipeline, new asset management, etc.). So this is basically a proof concept of events for images, and if this idea is not completely wrong I could improve it or help somehow.